home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / edit / thesrc20.zip / target.c < prev    next >
C/C++ Source or Header  |  1995-01-26  |  64KB  |  1,740 lines

  1. /***********************************************************************/
  2. /* TARGET.C - Functions related to targets.                            */
  3. /***********************************************************************/
  4. /*
  5.  * THE - The Hessling Editor. A text editor similar to VM/CMS xedit.
  6.  * Copyright (C) 1991-1995 Mark Hessling
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License as
  10.  * published by the Free Software Foundation; either version 2 of
  11.  * the License, or any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16.  * General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to:
  20.  *
  21.  *    The Free Software Foundation, Inc.
  22.  *    675 Mass Ave,
  23.  *    Cambridge, MA 02139 USA.
  24.  *
  25.  *
  26.  * If you make modifications to this software that you feel increases
  27.  * it usefulness for the rest of the community, please email the
  28.  * changes, enhancements, bug fixes as well as any and all ideas to me.
  29.  * This software is going to be maintained and enhanced as deemed
  30.  * necessary by the community.
  31.  *
  32.  * Mark Hessling                     email: M.Hessling@gu.edu.au
  33.  * 36 David Road                     Phone: +61 7 849 7731
  34.  * Holland Park                      Fax:   +61 7 875 5314
  35.  * QLD 4121
  36.  * Australia
  37.  */
  38.  
  39. /*
  40. $Id: target.c 2.0 1995/01/26 16:32:04 MH Release MH $
  41. */
  42.  
  43. #include <stdio.h>
  44. #include "the.h"
  45. #include "proto.h"
  46.  
  47. #define STATE_START    0
  48. #define STATE_DELIM    1
  49. #define STATE_STRING   2
  50. #define STATE_BOOLEAN  3
  51. #define STATE_NEXT     4
  52. #define STATE_POINT    5
  53. #define STATE_ABSOLUTE 6
  54. #define STATE_RELATIVE 7
  55. #define STATE_POSITIVE 8
  56. #define STATE_NEGATIVE 9
  57. #define STATE_SPARE    10
  58. #define STATE_QUIT     98
  59. #define STATE_ERROR    99
  60.  
  61. #ifdef PROTO
  62. static bool is_blank(LINE *);
  63. #else
  64. static bool is_blank();
  65. #endif
  66.  
  67. /***********************************************************************/
  68. #ifdef PROTO
  69. short split_change_params(CHARTYPE *cmd_line,CHARTYPE **old_str,CHARTYPE **new_str,
  70.                           TARGET *target,LINETYPE *num,LINETYPE *occ)
  71. #else
  72. short split_change_params(cmd_line,old_str,new_str,target,num,occ)
  73. CHARTYPE *cmd_line,**old_str,**new_str;
  74. TARGET *target;
  75. LINETYPE *num,*occ;
  76. #endif
  77. /***********************************************************************/
  78. {
  79. /*-------------------------- external data ----------------------------*/
  80. /*--------------------------- local data ------------------------------*/
  81. #define SCP_PARAMS  2
  82.  CHARTYPE *word[SCP_PARAMS+1];
  83.  register short i=0,j=0;
  84.  CHARTYPE *target_start=NULL;
  85.  short rc=RC_OK;
  86.  CHARTYPE delim=' ';
  87.  short idx=0;
  88.  short target_type = TARGET_NORMAL|TARGET_BLOCK_CURRENT|TARGET_ALL|TARGET_SPARE;
  89.  unsigned short num_params=0;
  90. /*--------------------------- processing ------------------------------*/
  91. #ifdef TRACE
  92.  trace_function("target.c:  split_change_params");
  93. #endif
  94. /*---------------------------------------------------------------------*/
  95. /* First, determine the delimiter; the first character in the argument */
  96. /* string.                                                             */
  97. /*---------------------------------------------------------------------*/
  98.  delim = *(cmd_line);
  99. /*---------------------------------------------------------------------*/
  100. /* Set up default values for the return values...                      */
  101. /*---------------------------------------------------------------------*/
  102.  *old_str = cmd_line+1;
  103.  *new_str = (CHARTYPE *)"";
  104.  target_start = (CHARTYPE *)"";
  105.  *num = *occ = 1L;
  106.  target->num_lines = 1L;
  107.  target->true_line = get_true_line();
  108. /*---------------------------------------------------------------------*/
  109. /* Set up default values for the return values...                      */
  110. /*---------------------------------------------------------------------*/
  111.  idx = strlen(cmd_line);
  112.  for (i=1,j=0;i<idx;i++)
  113.    {
  114.     if (*(cmd_line+i) == delim)
  115.       {
  116.        j++;
  117.        switch(j)
  118.          {
  119.           case 1:
  120.                *(cmd_line+i) = '\0';
  121.                *new_str = cmd_line+i+1;
  122.                break;
  123.           case 2:
  124.                *(cmd_line+i) = '\0';
  125.                target_start = cmd_line+i+1;
  126.                break;
  127.           default:
  128.                break;
  129.          }
  130.       }
  131.     if (j == 2)
  132.        break;
  133.    }
  134. /*---------------------------------------------------------------------*/
  135. /* Check to see if there is a target, if not return here.              */
  136. /*---------------------------------------------------------------------*/
  137.  if (blank_field(target_start))
  138.    {
  139. #ifdef TRACE
  140.     trace_return();
  141. #endif
  142.     return(RC_OK);
  143.    }
  144. /*---------------------------------------------------------------------*/
  145. /* Parse and validate the target...                                    */
  146. /*---------------------------------------------------------------------*/
  147.  if ((rc = validate_target(target_start,target,target_type,get_true_line(),TRUE,TRUE)) != RC_OK)
  148.    {
  149. #ifdef TRACE
  150.     trace_return();
  151. #endif
  152.     return(rc);
  153.    }
  154. /*---------------------------------------------------------------------*/
  155. /* Check to see if there are further arguments after the target...     */
  156. /*---------------------------------------------------------------------*/
  157.  if (target->spare == (-1))
  158.    {
  159. #ifdef TRACE
  160.     trace_return();
  161. #endif
  162.     return(RC_OK);
  163.    }
  164. /*---------------------------------------------------------------------*/
  165. /* Validate the arguments following the target...                      */
  166. /*---------------------------------------------------------------------*/
  167.  num_params = param_split(strtrunc(target->rt[target->spare].string),word,SCP_PARAMS,WORD_DELIMS,TEMP_PARAM);
  168.  if (num_params == 1
  169.  ||  num_params == 2)
  170.    {
  171.     if (strcmp(word[0],"*") == 0)
  172.        *num = MAX_LONG;
  173.     else
  174.        if (!valid_positive_integer(word[0]))
  175.          {
  176.           display_error(4,word[0],FALSE);
  177. #ifdef TRACE
  178.           trace_return();
  179. #endif
  180.           return(RC_INVALID_OPERAND);
  181.          }
  182.        else
  183.           *num = atol(word[0]);
  184.    }
  185.  if (num_params == 2)
  186.    {
  187.     if (!valid_positive_integer(word[1]))
  188.       {
  189.        display_error(4,word[1],FALSE);
  190. #ifdef TRACE
  191.        trace_return();
  192. #endif
  193.        return(RC_INVALID_OPERAND);
  194.       }
  195.     else
  196.        *occ = atol(word[1]);
  197.    }
  198.  
  199. #ifdef TRACE
  200.  trace_return();
  201. #endif
  202.  return(RC_OK);
  203. }
  204. /***********************************************************************/
  205. #ifdef PROTO
  206. short parse_target(CHARTYPE *target_spec,LINETYPE true_line,
  207.                    TARGET *target,short target_types,bool display_parse_error,
  208.                    bool allow_error_display)
  209. #else
  210. short parse_target(target_spec,true_line,target,target_types,display_parse_error,allow_error_display)
  211. CHARTYPE *target_spec;
  212. LINETYPE true_line;
  213. TARGET *target;
  214. short target_types;
  215. bool display_parse_error,allow_error_display;
  216. #endif
  217. /***********************************************************************/
  218. {
  219. /*-------------------------- external data ----------------------------*/
  220. /*--------------------------- local data ------------------------------*/
  221.  short num_targets=0;
  222.  CHARTYPE boolean=' ';
  223.  short state=STATE_NEXT;
  224.  short len=0,inc=0,target_length=strlen(target_spec),off=0;
  225.  CHARTYPE delim=' ';
  226.  register short i=0;
  227.  register short j=0;
  228.  short str_start=0,str_end=0;
  229.  short rtarget=0,rc=RC_OK;
  230.  short potential_spare_start=0;
  231.  bool negative=FALSE;
  232.  CHARTYPE *ptr=NULL;
  233.  LINETYPE lineno=0L;
  234. /*--------------------------- processing ------------------------------*/
  235. #ifdef TRACE
  236.  trace_function("target.c:  parse_target");
  237. #endif
  238. /*---------------------------------------------------------------------*/
  239. /* Copy the incoming target specification...                           */
  240. /*---------------------------------------------------------------------*/
  241.  if ((target->string = (CHARTYPE *)my_strdup(target_spec)) == NULL)
  242.    {
  243.     if (allow_error_display)
  244.        display_error(30,(CHARTYPE *)"",FALSE);
  245. #ifdef TRACE
  246.     trace_return();
  247. #endif
  248.     return(RC_OUT_OF_MEMORY);
  249.    }
  250.  ptr = target->string;
  251. /*---------------------------------------------------------------------*/
  252. /* Parse the target...                                                 */
  253. /*---------------------------------------------------------------------*/
  254.  while(1)
  255.    {
  256.     inc = 1;
  257.     switch(state)
  258.       {
  259.        case STATE_NEXT:
  260.             if (target->rt == NULL)
  261.                target->rt = (RTARGET *)(*the_malloc)((num_targets+1)*sizeof(RTARGET));
  262.             else
  263.                target->rt = (RTARGET *)(*the_realloc)(target->rt,(num_targets+1)*sizeof(RTARGET));
  264.             if (target->rt == NULL)
  265.               {
  266.                if (allow_error_display)
  267.                   display_error(30,(CHARTYPE *)"",FALSE);
  268. #ifdef TRACE
  269.                trace_return();
  270. #endif
  271.                return(RC_OUT_OF_MEMORY);
  272.               }
  273.             target->rt[num_targets].not = FALSE;
  274.             target->rt[num_targets].boolean = boolean;
  275.             target->rt[num_targets].length = 0;
  276.             target->rt[num_targets].string = NULL;
  277.             target->rt[num_targets].negative = FALSE;
  278.             target->rt[num_targets].target_type = TARGET_ERR;
  279.             if (target->spare != (-1))
  280.                state = STATE_SPARE;
  281.             else
  282.                state = STATE_START;
  283.             inc = 0;
  284.             break;
  285.        case STATE_START:
  286.             switch(*(ptr+i))
  287.               {
  288.                case '~': case '^':
  289.                     if (target->rt[num_targets].not)
  290.                       {
  291.                        state = STATE_ERROR;
  292.                        inc = 0;
  293.                        break;
  294.                       }
  295.                     target->rt[num_targets].not = TRUE;
  296.                     break;
  297.                case ' ': 
  298.                case '\t':
  299.                     break;
  300.                case '-':
  301.                     if (target->rt[num_targets].negative)
  302.                       {
  303.                        state = STATE_ERROR;
  304.                        inc = 0;
  305.                        break;
  306.                       }
  307.                     target->rt[num_targets].negative = TRUE;
  308.                     state = STATE_NEGATIVE;
  309.                     break;
  310.                case '+':
  311.                     if (target->rt[num_targets].negative)
  312.                       {
  313.                        state = STATE_ERROR;
  314.                        inc = 0;
  315.                        break;
  316.                       }
  317.                     inc = 1;
  318.                     break;
  319.                case '.':
  320.                     if (target->rt[num_targets].negative)
  321.                       {
  322.                        state = STATE_ERROR;
  323.                        inc = 0;
  324.                        break;
  325.                       }
  326.                     state = STATE_POINT;
  327.                     str_start = i;
  328.                     break;
  329.                case '*':
  330.                     state = STATE_BOOLEAN;
  331.                     target->rt[num_targets].target_type = TARGET_RELATIVE;
  332.                     target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(3);
  333.                     if (target->rt[num_targets].string == NULL)
  334.                       {
  335.                        if (allow_error_display)
  336.                           display_error(30,(CHARTYPE *)"",FALSE);
  337. #ifdef TRACE
  338.                        trace_return();
  339. #endif
  340.                        return(RC_OUT_OF_MEMORY);
  341.                       }
  342.                     if (target->rt[num_targets].negative)
  343.                       {
  344.                        target->rt[num_targets].numeric_target = true_line*(-1L);
  345.                        strcpy(target->rt[num_targets].string,"-*");
  346.                       }
  347.                     else
  348.                       {
  349.                        target->rt[num_targets].numeric_target = (CURRENT_FILE->number_lines - true_line) + 2;
  350.                        strcpy(target->rt[num_targets].string,"*");
  351.                       }
  352.                     inc = 1;
  353.                     potential_spare_start = i+1;
  354.                     num_targets++;
  355.                     break;
  356.                case ':': case ';':
  357.                     state = STATE_ABSOLUTE;
  358.                     delim = *(ptr+i);
  359.                     str_start = i+1;
  360.                     break;
  361.                case '/': case '\\': case '@':
  362.                     state = STATE_STRING;
  363.                     str_start = i+1;
  364.                     delim = *(ptr+i);
  365.                     break;
  366.                case 'a': case 'A':
  367.                     if (target->rt[num_targets].not
  368.                     ||  target->rt[num_targets].negative)
  369.                       {
  370.                        state = STATE_ERROR;
  371.                        inc = 0;
  372.                        break;
  373.                       }
  374.                     if (target_length-i < 3)
  375.                       {
  376.                        target->rt[num_targets].target_type = TARGET_ERR;
  377.                        state = STATE_ERROR;
  378.                        inc = 0;
  379.                        break;
  380.                       }
  381.                     if (memcmpi("all",ptr+i,3) == 0
  382.                     && (*(ptr+(i+3)) == ' ' 
  383.                         || *(ptr+(i+3)) == '\0'
  384.                         || *(ptr+(i+3)) == '\t'))
  385.                       {
  386.                        target->rt[num_targets].target_type = TARGET_ALL;
  387.                        inc = 3;
  388.                        state = STATE_BOOLEAN;
  389.                        num_targets++;
  390.                        potential_spare_start = i+3;
  391.                        break;
  392.                       }
  393.                     state = STATE_ERROR;
  394.                     inc = 0;
  395.                     break;
  396.                case 'b': case 'B':
  397.                     if (target_length-i < 5)
  398.                       {
  399.                        state = STATE_ERROR;
  400.                        inc = 0;
  401.                        break;
  402.                       }
  403.                     if (memcmpi("blank",ptr+i,5) == 0
  404.                     && (*(ptr+(i+5)) == ' ' 
  405.                         || *(ptr+(i+5)) == '\0'
  406.                         || *(ptr+(i+5)) == '\t'))
  407.                       {
  408.                        target->rt[num_targets].target_type = TARGET_BLANK;
  409.                        inc = 5;
  410.                        potential_spare_start = i+5;
  411.                        state = STATE_BOOLEAN;
  412.                        num_targets++;
  413.                        break;
  414.                       }
  415.                     if (target->rt[num_targets].not
  416.                     ||  target->rt[num_targets].negative)
  417.                       {
  418.                        state = STATE_ERROR;
  419.                        inc = 0;
  420.                        break;
  421.                       }
  422.                     if (memcmpi("block",ptr+i,5) == 0
  423.                     && (*(ptr+(i+5)) == ' ' 
  424.                         || *(ptr+(i+5)) == '\0'
  425.                         || *(ptr+(i+5)) == '\t'))
  426.                       {
  427.                        target->rt[num_targets].target_type = TARGET_BLOCK;
  428.                        inc = 5;
  429.                        potential_spare_start = i+5;
  430.                        state = STATE_BOOLEAN;
  431.                        num_targets++;
  432.                        break;
  433.                       }
  434.                     state = STATE_ERROR;
  435.                     inc = 0;
  436.                     break;
  437.                case '0': case '1': case '2': case '3': case '4': 
  438.                case '5': case '6': case '7': case '8': case '9':      
  439.                     state = STATE_RELATIVE;
  440.                     str_start = i;
  441.                     delim = '\0';
  442.                     inc = 0;
  443.                     break;
  444.                default:
  445.                     state = STATE_ERROR;
  446.                     inc = 0;
  447.                     break;
  448.               }
  449.             break;
  450.        case STATE_STRING:
  451.             switch(*(ptr+i))
  452.               {
  453.                case '/': case '\\': case '@':
  454.                case '\0':
  455.                     if (*(ptr+i) == delim
  456.                     ||  *(ptr+i) == '\0')
  457.                       {
  458.                        state = STATE_BOOLEAN;
  459.                        str_end = i;
  460.                        len = str_end-str_start;
  461.                        target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(len+1);
  462.                        if (target->rt[num_targets].string == NULL)
  463.                          {
  464.                           if (allow_error_display)
  465.                              display_error(30,(CHARTYPE *)"",FALSE);
  466. #ifdef TRACE
  467.                           trace_return();
  468. #endif
  469.                           return(RC_OUT_OF_MEMORY);
  470.                          }
  471.                        memcpy(target->rt[num_targets].string,ptr+str_start,len);
  472.                        target->rt[num_targets].string[len] = '\0';
  473.                        target->rt[num_targets].length = len;
  474.                        target->rt[num_targets].target_type = TARGET_STRING;
  475.                        potential_spare_start = i+1;
  476.                        num_targets++;
  477.                       }
  478.                     break;
  479.                default:
  480.                     break;
  481.               }
  482.             break;
  483.        case STATE_BOOLEAN:
  484.             switch(*(ptr+i))
  485.               {
  486.                case '\0':
  487.                     break;
  488.                case ' ': 
  489.                case '\t':
  490.                     break;
  491.                case '&': 
  492.                case '|':
  493.                     state = STATE_NEXT;
  494.                     boolean = *(ptr+i);
  495.                     break;
  496.                default:
  497.                     if (target_types & TARGET_SPARE)
  498.                       {
  499. /*                       str_start = i;*/
  500.                        str_start = potential_spare_start;
  501.                        state = STATE_NEXT;
  502.                        target->spare = 0; /* just to ensure state is set */
  503.                        break;
  504.                       }
  505.                     state = STATE_ERROR;
  506.                     inc = 0;
  507.                     break;
  508.               }
  509.             break;
  510.        case STATE_SPARE:
  511.             switch(*(ptr+i))
  512.               {
  513.                case '\0':
  514.                     str_end = i;
  515.                     len = str_end-str_start;
  516.                     target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(len+1);
  517.                     if (target->rt[num_targets].string == NULL)
  518.                       {
  519.                        if (allow_error_display)
  520.                           display_error(30,(CHARTYPE *)"",FALSE);
  521. #ifdef TRACE
  522.                        trace_return();
  523. #endif
  524.                        return(RC_OUT_OF_MEMORY);
  525.                       }
  526.                     memcpy(target->rt[num_targets].string,ptr+str_start,len);
  527.                     target->rt[num_targets].string[len] = '\0';
  528.                     target->rt[num_targets].length = len;
  529.                     target->rt[num_targets].target_type = TARGET_SPARE;
  530.                     target->spare = num_targets;
  531.                     num_targets++;
  532.                     *(ptr+str_start) = '\0'; /* so target string does not include spare */
  533.                     break;
  534.                default:
  535.                     break;
  536.               }
  537.             break;
  538.        case STATE_ABSOLUTE:
  539.        case STATE_RELATIVE:
  540.             if (target->rt[num_targets].not)
  541.               {
  542.                state = STATE_ERROR;
  543.                inc = 0;
  544.                break;
  545.               }
  546.             switch(*(ptr+i))
  547.               {
  548.                case '\0':
  549.                case ' ':
  550.                case '\t':
  551.                     str_end = i;
  552.                     len = str_end-str_start;
  553.                     target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(len+2);
  554.                     if (target->rt[num_targets].string == NULL)
  555.                       {
  556.                        if (allow_error_display)
  557.                           display_error(30,(CHARTYPE *)"",FALSE);
  558. #ifdef TRACE
  559.                        trace_return();
  560. #endif
  561.                        return(RC_OUT_OF_MEMORY);
  562.                       }
  563.                     if (delim != '\0')
  564.                       {
  565.                        target->rt[num_targets].string[0] = delim;
  566.                        off = 1;
  567.                       }
  568.                     else
  569.                        off = 0;
  570.                     memcpy(target->rt[num_targets].string+off,ptr+str_start,len);
  571.                     target->rt[num_targets].string[len+off] = '\0';
  572.                     target->rt[num_targets].length = len+off;
  573.                     target->rt[num_targets].target_type = (state == STATE_ABSOLUTE) ? TARGET_ABSOLUTE : TARGET_RELATIVE;
  574.                     target->rt[num_targets].numeric_target = atol(target->rt[num_targets].string+off);
  575.                     if (target->rt[num_targets].negative)
  576.                        target->rt[num_targets].numeric_target *= (-1L);
  577.                     if (state == STATE_ABSOLUTE)
  578.                       {
  579.                        if (target->rt[num_targets].numeric_target < true_line)
  580.                           target->rt[num_targets].negative = TRUE;
  581.                        else
  582.                           target->rt[num_targets].numeric_target = min(target->rt[num_targets].numeric_target,(CURRENT_FILE->number_lines+1L));
  583.                       }
  584.                     else
  585.                       {
  586.                        if (target->rt[num_targets].negative)
  587.                           target->rt[num_targets].numeric_target = max((target->rt[num_targets].numeric_target),(true_line == 0L) ? (0L) : (true_line*(-1L)));
  588.                        else
  589.                           target->rt[num_targets].numeric_target = min(target->rt[num_targets].numeric_target,(CURRENT_FILE->number_lines - true_line+1L));
  590.                       }
  591.                     potential_spare_start = i;
  592.                     num_targets++;
  593.                     state = STATE_BOOLEAN;
  594.                     break;
  595.                case '0': case '1': case '2': case '3': case '4':
  596.                case '5': case '6': case '7': case '8': case '9':
  597.                     break;
  598.                default:
  599.                     state = STATE_ERROR;
  600.                     inc = 0;
  601.                     break;
  602.               }
  603.             break;
  604.        case STATE_NEGATIVE:
  605.             switch(*(ptr+i))
  606.               {
  607.                case '0': case '1': case '2': case '3': case '4':
  608.                case '5': case '6': case '7': case '8': case '9':
  609.                     state = STATE_RELATIVE;
  610.                     delim = '-';
  611.                     str_start = i;
  612.                     inc = 0;
  613.                     break;
  614.                case '/': case '\\': case '@':
  615.                     state = STATE_START;
  616.                     inc = 0;
  617.                     break;
  618.                case '*':
  619.                     state = STATE_START;
  620.                     inc = 0;
  621.                     break;
  622.                case 'b': case 'B':
  623.                     state = STATE_START;
  624.                     inc = 0;
  625.                     break;
  626.                default:
  627.                     state = STATE_ERROR;
  628.                     inc = 0;
  629.                     break;
  630.               }
  631.             break;
  632.        case STATE_POINT:
  633.             switch(*(ptr+i))
  634.               {
  635.                case ' ':
  636.                case '\t':
  637.                     state = STATE_BOOLEAN;
  638.                     /* fall through */
  639.                case '&':
  640.                case '|':
  641.                case '\0':
  642.                     target->rt[num_targets].target_type = TARGET_POINT;
  643.                     str_end = i;
  644.                     len = str_end-str_start;
  645.                     target->rt[num_targets].string = (CHARTYPE *)(*the_malloc)(len+1);
  646.                     if (target->rt[num_targets].string == NULL)
  647.                       {
  648.                        if (allow_error_display)
  649.                           display_error(30,(CHARTYPE *)"",FALSE);
  650. #ifdef TRACE
  651.                        trace_return();
  652. #endif
  653.                        return(RC_OUT_OF_MEMORY);
  654.                       }
  655.                     memcpy(target->rt[num_targets].string,ptr+str_start,len);
  656.                     target->rt[num_targets].string[len] = '\0';
  657.                     target->rt[num_targets].length = len;
  658.                     if (find_named_line(target->rt[num_targets].string,&lineno,TRUE) == NULL)
  659.                       {
  660.                        state = STATE_ERROR;
  661.                        break;
  662.                       }
  663.                     target->rt[num_targets].numeric_target = lineno;
  664.                     if (target->rt[num_targets].numeric_target < true_line)
  665.                        target->rt[num_targets].negative = TRUE;
  666.                     else
  667.                        target->rt[num_targets].numeric_target = min(target->rt[num_targets].numeric_target,(CURRENT_FILE->number_lines+1L));
  668.                     num_targets++;
  669.                     potential_spare_start = i;
  670.                     if (*(ptr+i) == ' ' || *(ptr+i) == '\t')
  671.                        break;
  672.                     boolean = *(ptr+i);
  673.                     state = STATE_NEXT;
  674.                     break;
  675.                default:
  676.                     break;
  677.               }
  678.             break;
  679.        case STATE_ERROR:
  680.             for (j=0;j<num_targets;j++)
  681.                target->rt[j].target_type = TARGET_ERR;
  682.             state = STATE_QUIT;
  683.             break;
  684.       }
  685.     if (state == STATE_QUIT)
  686.        break;
  687.     i += inc;
  688.     if (i > target_length) /* this allows for testing '\0' as delimiter */
  689.        break;
  690.    }
  691.  target->num_targets = num_targets;
  692.  if (num_targets == 0
  693.  ||  target->rt[0].target_type == TARGET_ERR)
  694.    {
  695.     if (display_parse_error
  696.     && allow_error_display)
  697.        display_error(1,ptr,FALSE);
  698. #ifdef TRACE
  699.     trace_return();
  700. #endif
  701.     return(RC_INVALID_OPERAND);
  702.    }
  703. /*---------------------------------------------------------------------*/
  704. /* Time to validate the targets we have parsed...                      */
  705. /*---------------------------------------------------------------------*/
  706. /* Valid combinations are:                                             */
  707. /* TARGET_ALL       (1 target only)                                    */
  708. /*                  ALL  only                                          */
  709. /* TARGET_BLOCK     (1 target only)                                    */
  710. /*                  BLOCK  only                                        */
  711. /*                  this section sets target_type to TARGET_BLOCK_ANY  */
  712. /*                  or TARGET_BLOCK_CURRENT                            */
  713. /* TARGET_BLANK     (BLANK can be upper or lower case)                 */
  714. /*                  BLANK                                              */
  715. /*                  -BLANK                                             */
  716. /*                  ~BLANK                                             */
  717. /*                  ~-BLANK                                            */
  718. /* TARGET_STRING    (valid delimiters are / \ or @                     */
  719. /*                  /string/                                           */
  720. /*                  -/string/                                          */
  721. /*                  ~/string/                                          */
  722. /*                  ~-/string/                                         */
  723. /* TARGET_POINT                                                        */
  724. /*                  .xxxxxx                                            */
  725. /*                  ~.xxxxxx                                           */
  726. /* TARGET_ABSOLUTE                                                     */
  727. /*                  :99                                                */
  728. /*                  ;99                                                */
  729. /* TARGET_RELATIVE                                                     */
  730. /*                  99                                                 */
  731. /*                  +99                                                */
  732. /*                  -99                                                */
  733. /*                  *                                                  */
  734. /*                  +*                                                 */
  735. /*                  -*                                                 */
  736. /*                                                                     */
  737. /* Any of the above target types may be or'd together.                 */
  738. /*---------------------------------------------------------------------*/
  739. /*---------------------------------------------------------------------*/
  740. /* For each of the targets, check its validity...                      */
  741. /*---------------------------------------------------------------------*/
  742.  negative = target->rt[0].negative;
  743.  for (i=0;i<num_targets-((target->spare == (-1)) ? 0 : 1);i++)
  744.    {
  745.     switch(target->rt[i].target_type)
  746.       {
  747.        case TARGET_BLOCK:
  748.             if (num_targets-((target->spare == (-1)) ? 0 : 1) != 1)
  749.               {
  750.                rc = RC_INVALID_OPERAND;
  751.                break;
  752.               }
  753.             if (target_types & TARGET_BLOCK_ANY)
  754.                target->rt[i].target_type = TARGET_BLOCK_ANY;
  755.             else
  756.                if (target_types & TARGET_BLOCK_CURRENT)
  757.                   target->rt[i].target_type = TARGET_BLOCK_CURRENT;
  758.                else
  759.                   rc = RC_INVALID_OPERAND;
  760.             break;
  761.        case TARGET_ALL:
  762.             if (num_targets-((target->spare == (-1)) ? 0 : 1) != 1)
  763.               {
  764.                rc = RC_INVALID_OPERAND;
  765.                break;
  766.               }
  767.             if (target_types & target->rt[i].target_type)
  768.                break;
  769.             rc = RC_INVALID_OPERAND;
  770.             break;
  771.        default:
  772.             if (target->rt[i].negative != negative)
  773.               {
  774.                rc = RC_INVALID_OPERAND;
  775.                break;
  776.               }
  777.             if (target_types & target->rt[i].target_type)
  778.                break;
  779.             rc = RC_INVALID_OPERAND;
  780.             break;
  781.       }
  782.     if (rc == RC_INVALID_OPERAND)
  783.        break;
  784.    }
  785. /*---------------------------------------------------------------------*/
  786. /* Display an error if anything found amiss and we are directed to     */
  787. /* display an error...                                                 */
  788. /*---------------------------------------------------------------------*/
  789.  if (rc != RC_OK
  790.  && display_parse_error
  791.  && allow_error_display)
  792.     display_error(1,ptr,FALSE);
  793. #ifdef TRACE
  794.  trace_return();
  795. #endif
  796.  return(rc);
  797. }
  798. /***********************************************************************/
  799. #ifdef PROTO
  800. void initialise_target(TARGET *target)
  801. #else
  802. void initialise_target(target)
  803. TARGET *target;
  804. #endif
  805. /***********************************************************************/
  806. {
  807. /*--------------------------- local data ------------------------------*/
  808. /*--------------------------- processing ------------------------------*/
  809. #ifdef TRACE
  810.  trace_function("target.c:  initialise_target");
  811. #endif
  812.  target->rt=NULL;
  813.  target->string=NULL;
  814.  target->num_lines = target->true_line = 0L;
  815.  target->num_targets = 0;
  816.  target->spare = (-1);
  817.  target->ignore_scope = FALSE;
  818. #ifdef TRACE
  819.  trace_return();
  820. #endif
  821.  return;
  822. }
  823. /***********************************************************************/
  824. #ifdef PROTO
  825. void free_target(TARGET *target)
  826. #else
  827. void free_target(target)
  828. TARGET *target;
  829. #endif
  830. /***********************************************************************/
  831. {
  832. /*--------------------------- local data ------------------------------*/
  833.  register short i=0;
  834. /*--------------------------- processing ------------------------------*/
  835. #ifdef TRACE
  836.  trace_function("target.c:  free_target");
  837. #endif
  838.  if (target->string == NULL
  839.  &&  target->num_targets == 0
  840.  &&  target->rt == NULL)
  841.    {
  842. #ifdef TRACE
  843.     trace_return();
  844. #endif
  845.     return;
  846.    }
  847.  for (i=0;i<target->num_targets;i++)
  848.    {
  849.     if (target->rt[i].string != NULL)
  850.        (*the_free)(target->rt[i].string);
  851.    }
  852.  if (target->string != NULL)
  853.     (*the_free)(target->string);
  854.  if (target->rt != NULL)
  855.     (*the_free)(target->rt);
  856. #ifdef TRACE
  857.  trace_return();
  858. #endif
  859.  return;
  860. }
  861. /***********************************************************************/
  862. #ifdef PROTO
  863. short find_target(TARGET *target,LINETYPE true_line,bool display_parse_error,bool allow_error_display)
  864. #else
  865. short find_target(target,true_line,display_parse_error,allow_error_display)
  866. TARGET *target;
  867. LINETYPE true_line;
  868. bool display_parse_error,allow_error_display;
  869. #endif
  870. /***********************************************************************/
  871. {
  872. /*-------------------------- external data ----------------------------*/
  873.  extern bool in_profile;
  874.  extern VIEW_DETAILS *vd_mark;
  875. /*--------------------------- local data ------------------------------*/
  876.  short rc=RC_OK;
  877.  LINE *curr=NULL;
  878.  LINETYPE num_lines=0L;
  879.  LINETYPE line_number=0L;
  880.  bool status=FALSE;
  881. /*--------------------------- processing ------------------------------*/
  882. #ifdef TRACE
  883.  trace_function("target.c:  find_target");
  884. #endif
  885. /*---------------------------------------------------------------------*/
  886. /* Check single targets first (ALL and BLOCK)                          */
  887. /*---------------------------------------------------------------------*/
  888. /*---------------------------------------------------------------------*/
  889. /* Check if first, and only target, is BLOCK...                        */
  890. /*---------------------------------------------------------------------*/
  891.  switch(target->rt[0].target_type)
  892.    {
  893.     case TARGET_ALL:
  894.          target->true_line = 1L;
  895.          target->num_lines = CURRENT_FILE->number_lines;
  896. #ifdef TRACE
  897.          trace_return();
  898. #endif
  899.          return(RC_OK);
  900.          break;
  901.     case TARGET_BLOCK_ANY:
  902.          if (MARK_VIEW == NULL)
  903.            {
  904.             if (allow_error_display)
  905.                display_error(44,"",FALSE);
  906.             rc = RC_TARGET_NOT_FOUND;
  907.            }
  908.          else
  909.            {
  910.             target->num_lines = MARK_VIEW->mark_end_line - MARK_VIEW->mark_start_line + 1L;
  911.             target->true_line = MARK_VIEW->mark_start_line;
  912.            }
  913. #ifdef TRACE
  914.          trace_return();
  915. #endif
  916.          return(rc);
  917.          break;
  918.     case TARGET_BLOCK_CURRENT:
  919.          if (MARK_VIEW == NULL)
  920.            {
  921.             if (allow_error_display)
  922.                display_error(44,"",FALSE);
  923.             rc = RC_TARGET_NOT_FOUND;
  924.            }
  925.          else
  926.            {
  927.             if (MARK_VIEW != CURRENT_VIEW)
  928.               {
  929.                if (allow_error_display)
  930.                   display_error(45,"",FALSE);
  931.                rc = RC_TARGET_NOT_FOUND;
  932.               }
  933.             else
  934.               {
  935.                target->num_lines = MARK_VIEW->mark_end_line - MARK_VIEW->mark_start_line + 1L;
  936.                target->true_line = MARK_VIEW->mark_start_line;
  937.               }
  938.            }
  939. #ifdef TRACE
  940.          trace_return();
  941. #endif
  942.          return(rc);
  943.          break;
  944.     default:
  945.          break;
  946.    }
  947. /*---------------------------------------------------------------------*/
  948. /* All other targets are potentially repeating targets...              */
  949. /*---------------------------------------------------------------------*/
  950.  rc = RC_TARGET_NOT_FOUND;
  951.  status = FALSE;
  952.  line_number = true_line;
  953.  curr = lll_find(CURRENT_FILE->first_line,true_line);
  954.  num_lines = 0L;
  955.  while(1)
  956.    {
  957.     status = find_rtarget_target(curr,target,true_line,line_number,&num_lines);
  958.     if (status)
  959.        break;
  960. /*---------------------------------------------------------------------*/
  961. /* We can determine the direction of execution based on the first      */
  962. /* target, as all targets must have the same direction to have reached */
  963. /* here.                                                               */
  964. /*---------------------------------------------------------------------*/
  965.     if (target->rt[0].negative)
  966.       {
  967.        curr = curr->prev;
  968.        line_number--;
  969.       }
  970.     else
  971.       {
  972.        curr = curr->next;
  973.        line_number++;
  974.       }
  975.     if (curr == NULL)
  976.        break;
  977.    }
  978.  if (status)
  979.    {
  980.     num_lines = ((target->rt[0].negative) ? -num_lines : num_lines);
  981.     target->num_lines = num_lines;
  982.     target->true_line = true_line;
  983.     rc = RC_OK;
  984.    }
  985.  else
  986.    {
  987.     if (allow_error_display)
  988.        display_error(17,target->string,FALSE);
  989.     rc = RC_TARGET_NOT_FOUND;
  990.    }
  991. #ifdef TRACE
  992.  trace_return();
  993. #endif
  994.  return(rc);
  995. }
  996. /***********************************************************************/
  997. #ifdef PROTO
  998. static bool is_blank(LINE *curr)
  999. #else
  1000. static bool is_blank(curr)
  1001. LINE *curr;
  1002. #endif
  1003. /***********************************************************************/
  1004. {
  1005. /*-------------------------- external data ----------------------------*/
  1006. /*--------------------------- local data ------------------------------*/
  1007.  register short i=0;
  1008.  bool rc=TRUE;
  1009. /*--------------------------- processing ------------------------------*/
  1010. #ifdef TRACE
  1011.  trace_function("target.c:  is_blank");
  1012. #endif
  1013.  if (CURRENT_VIEW->zone_start > curr->length)
  1014.    {
  1015. #ifdef TRACE
  1016.     trace_return();
  1017. #endif
  1018.     return(TRUE);
  1019.    }
  1020.  for (i=CURRENT_VIEW->zone_start-1;i<min(CURRENT_VIEW->zone_end,curr->length);i++)
  1021.    {
  1022.     if (*(curr->line+i) != ' ')
  1023.       {
  1024.        rc = FALSE;
  1025.        break;
  1026.       }
  1027.    }
  1028. #ifdef TRACE
  1029.  trace_return();
  1030. #endif
  1031.  return(rc);
  1032. }
  1033. /***********************************************************************/
  1034. #ifdef PROTO
  1035. LINE *find_named_line(CHARTYPE *name,LINETYPE *retline,bool respect_scope)
  1036. #else
  1037. LINE *find_named_line(name,retline,respect_scope)
  1038. CHARTYPE *name;
  1039. LINETYPE *retline;
  1040. bool respect_scope;
  1041. #endif
  1042. /***********************************************************************/
  1043. {
  1044. /*-------------------------- external data ----------------------------*/
  1045. /*--------------------------- local data ------------------------------*/
  1046.  LINETYPE lineno=0;
  1047.  LINE *curr=NULL;
  1048. /*--------------------------- processing ------------------------------*/
  1049. #ifdef TRACE
  1050.  trace_function("target.c:  find_named_line");
  1051. #endif
  1052. /*---------------------------------------------------------------------*/
  1053. /* Find the line number in the current file of the named line specified*/
  1054. /*---------------------------------------------------------------------*/
  1055.  curr = CURRENT_FILE->first_line;
  1056.  while(curr->next != (LINE *)NULL)
  1057.    {
  1058. /*---------------------------------------------------------------------*/
  1059. /* Check the line's name if we are not respecting scope or if we are   */
  1060. /* respecting scope and the line is in scope.                          */
  1061. /*---------------------------------------------------------------------*/
  1062.     if (!respect_scope
  1063.     || (respect_scope && (in_scope(curr) || CURRENT_VIEW->scope_all)))
  1064.       {
  1065.        if (curr->name != (CHARTYPE *)NULL)
  1066.           if (strcmp(curr->name,name) == 0)
  1067.             {
  1068. #ifdef TRACE
  1069.              trace_return();
  1070. #endif
  1071.              *retline = lineno;
  1072.              return(curr);
  1073.             }
  1074.       }
  1075.     lineno++;
  1076.     curr = curr->next;
  1077.    }
  1078. #ifdef TRACE
  1079.  trace_return();
  1080. #endif
  1081.  return((LINE *)NULL);
  1082. }
  1083. /***********************************************************************/
  1084. #ifdef PROTO
  1085. short find_string_target(LINE *curr,RTARGET *rt)
  1086. #else
  1087. short find_string_target(curr,rt)
  1088. LINE *curr;
  1089. RTARGET *rt;
  1090. #endif
  1091. /***********************************************************************/
  1092. {
  1093. /*-------------------------- external data ----------------------------*/
  1094.  extern CHARTYPE *rec;
  1095. /*--------------------------- local data ------------------------------*/
  1096.  CHARTYPE *needle=(CHARTYPE *)rt->string;
  1097.  CHARTYPE *haystack=curr->line;
  1098.  LENGTHTYPE needle_length=0,haystack_length=0,real_start=0,real_end=0;
  1099.  bool use_rec=FALSE;
  1100.  short rc=RC_OK;
  1101.  short loc=0;
  1102. /*--------------------------- processing ------------------------------*/
  1103. #ifdef TRACE
  1104.  trace_function("target.c:  find_string_target");
  1105. #endif
  1106. /*---------------------------------------------------------------------*/
  1107. /* Copy contents of rec into linked to ensure that changes made are    */
  1108. /* included in the linked list searched.                               */
  1109. /*---------------------------------------------------------------------*/
  1110.  post_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line);
  1111. /*---------------------------------------------------------------------*/
  1112. /* If HEX is on, convert the target from a HEX format to CHARTYPE.     */
  1113. /*---------------------------------------------------------------------*/
  1114.  if (CURRENT_VIEW->hex == TRUE)
  1115.    {
  1116.     rc = convert_hex_strings(needle);
  1117.     if (rc == (-1))
  1118.       {
  1119.        display_error(32,(CHARTYPE *)"",FALSE);
  1120. #ifdef TRACE
  1121.        trace_return();
  1122. #endif
  1123.        return(RC_INVALID_OPERAND);
  1124.       }
  1125.     else
  1126.       needle_length = rc;
  1127.    }
  1128.  else
  1129.    needle_length = strlen(needle);
  1130. /*---------------------------------------------------------------------*/
  1131. /* Determine if we need to copy the contents of the line into rec.     */
  1132. /* The reasons we need to do this are:                                 */
  1133. /* - the length of the needle is 0                                     */
  1134. /* - the last character of needle is a space                           */
  1135. /*---------------------------------------------------------------------*/
  1136.  if (needle_length == 0)
  1137.     use_rec = TRUE;
  1138.  else
  1139.     if (*(needle+(needle_length-1)) == ' ')
  1140.        use_rec = TRUE;
  1141.  
  1142.  if (use_rec)
  1143.    {
  1144.     memset(rec,' ',max_line_length);
  1145.     memcpy(rec,curr->line,curr->length);
  1146.     haystack = rec;
  1147.     haystack_length = max_line_length;
  1148.    }
  1149.  else
  1150.    {
  1151.     haystack = curr->line;
  1152.     haystack_length = curr->length;
  1153.    }
  1154. /*---------------------------------------------------------------------*/
  1155. /* Calculate the bounds to search in based on length of haystack and   */
  1156. /* ZONE settings.                                                      */
  1157. /*---------------------------------------------------------------------*/
  1158.  real_end = min(haystack_length,CURRENT_VIEW->zone_end-1);
  1159.  real_start = max(0,CURRENT_VIEW->zone_start-1);
  1160. /*---------------------------------------------------------------------*/
  1161. /* Find the needle in the haystack.                                    */
  1162. /*---------------------------------------------------------------------*/
  1163.  loc = memfind(haystack+real_start,needle,(real_end-real_start+1),
  1164.                   needle_length,(CURRENT_VIEW->case_locate == CASE_IGNORE) ? TRUE : FALSE,
  1165.                   CURRENT_VIEW->arbchar_status,
  1166.                   CURRENT_VIEW->arbchar_single,
  1167.                   CURRENT_VIEW->arbchar_multiple);
  1168.  if (loc == (-1))
  1169.     rc = RC_TARGET_NOT_FOUND;
  1170.  else
  1171.     rc = RC_OK;
  1172. /*---------------------------------------------------------------------*/
  1173. /* Copy contents of linked list into rec if we have used rec as a work */
  1174. /* area.                                                               */
  1175. /*---------------------------------------------------------------------*/
  1176.  if (use_rec)
  1177.     pre_process_line(CURRENT_VIEW,CURRENT_VIEW->focus_line);
  1178. #ifdef TRACE
  1179.  trace_return();
  1180. #endif
  1181.  return(rc);
  1182. }
  1183. /***********************************************************************/
  1184. #ifdef PROTO
  1185. bool find_rtarget_target(LINE *curr,TARGET *target,LINETYPE true_line,LINETYPE line_number,LINETYPE *num_lines)
  1186. #else
  1187. bool find_rtarget_target(curr,target,true_line,line_number,num_lines)
  1188. LINE *curr;
  1189. TARGET *target;
  1190. LINETYPE true_line,line_number;
  1191. LINETYPE *num_lines;
  1192. #endif
  1193. /***********************************************************************/
  1194. {
  1195. /*-------------------------- external data ----------------------------*/
  1196. /*--------------------------- local data ------------------------------*/
  1197.  register short i=0;
  1198.  bool target_found=FALSE,status=FALSE;
  1199.  LINETYPE multiplier=0;
  1200. /*--------------------------- processing ------------------------------*/
  1201. #ifdef TRACE
  1202.  trace_function("target.c:  find_rtarget_target");
  1203. #endif
  1204. /*---------------------------------------------------------------------*/
  1205. /* If the line is not in scope and scope is respected, return FALSE.   */
  1206. /*---------------------------------------------------------------------*/
  1207.  if (!(in_scope(curr))
  1208.  &&  !target->ignore_scope)
  1209.    {
  1210.     if (!CURRENT_VIEW->scope_all
  1211.     && !TOF(line_number)
  1212.     && !BOF(line_number))
  1213.       {
  1214. #ifdef TRACE
  1215.        trace_return();
  1216. #endif
  1217.        return(FALSE);
  1218.       }
  1219.    }
  1220.  if (line_number != true_line)
  1221.     *num_lines = *num_lines + 1L;
  1222.  for (i=0;i<target->num_targets-((target->spare == (-1)) ? 0 : 1);i++)
  1223.    {
  1224.     target_found = FALSE;
  1225.     multiplier = (target->rt[i].negative) ? -1L : 1L;
  1226.     switch(target->rt[i].target_type)
  1227.       {
  1228.        case TARGET_BLANK:
  1229.             if (true_line == line_number)
  1230.               {
  1231.                target_found = ((target->rt[i].not) ? TRUE : FALSE);
  1232.                break;
  1233.               }
  1234.             if (target->rt[0].negative)
  1235.               {
  1236.                if (curr->prev == NULL)
  1237.                   break;
  1238.               }
  1239.             else
  1240.               {
  1241.                if (curr->next == NULL)
  1242.                   break;
  1243.               }
  1244.             target_found = is_blank(curr);
  1245.             break;
  1246.        case TARGET_POINT:
  1247.             if (true_line == line_number)
  1248.               {
  1249.                target_found = ((target->rt[i].not) ? TRUE : FALSE);
  1250.                break;
  1251.               }
  1252.             if (curr->name == (CHARTYPE *)NULL)
  1253.                break;
  1254.             if (strcmp(curr->name,target->rt[i].string) == 0)
  1255.                target_found = TRUE;
  1256.             break;
  1257.        case TARGET_STRING:
  1258.             if (true_line == line_number)
  1259.               {
  1260.                target_found = ((target->rt[i].not) ? TRUE : FALSE);
  1261.                break;
  1262.               }
  1263.             if (target->rt[0].negative)
  1264.               {
  1265.                if (curr->prev == NULL)
  1266.                   break;
  1267.               }
  1268.             else
  1269.               {
  1270.                if (curr->next == NULL)
  1271.                   break;
  1272.               }
  1273.             if (find_string_target(curr,&target->rt[i]) == RC_OK)
  1274.                target_found = TRUE;
  1275.             break;
  1276.        case TARGET_RELATIVE:
  1277.             if ((*num_lines * multiplier) == target->rt[i].numeric_target)
  1278.                   target_found = TRUE;
  1279.             if (target->rt[0].negative)
  1280.               {
  1281.                if (curr->prev == NULL)
  1282.                  {
  1283.                   target_found = TRUE;
  1284.                   break;
  1285.                  }
  1286.               }
  1287.             else
  1288.               {
  1289.                if (curr->next == NULL)
  1290.                  {
  1291.                   target_found = TRUE;
  1292.                   break;
  1293.                  }
  1294.               }
  1295.             break;
  1296.        case TARGET_ABSOLUTE:
  1297.             if (line_number == target->rt[i].numeric_target)
  1298.                   target_found = TRUE;
  1299.             break;
  1300.        default:
  1301.             break;
  1302.       }
  1303.     if (target->rt[i].not)
  1304.        target_found = (target_found) ? FALSE : TRUE;
  1305.     switch(target->rt[i].boolean)
  1306.       {
  1307.        case ' ':
  1308.             status = target_found;
  1309.             break;
  1310.        case '&':
  1311.             status &= target_found;
  1312.             break;
  1313.        case '|':
  1314.             status |= target_found;
  1315.             break;
  1316.       }
  1317.    }
  1318. #ifdef TRACE
  1319.  trace_return();
  1320. #endif
  1321.  return(status);
  1322. }
  1323. /***********************************************************************/
  1324. #ifdef PROTO
  1325. LINETYPE find_next_in_scope(LINE *in_curr,LINETYPE line_number,short direction)
  1326. #else
  1327. LINETYPE find_next_in_scope(in_curr,line_number,direction)
  1328. LINE *in_curr;
  1329. LINETYPE line_number;
  1330. short direction;
  1331. #endif
  1332. /***********************************************************************/
  1333. {
  1334. /*-------------------------- external data ----------------------------*/
  1335. /*--------------------------- local data ------------------------------*/
  1336.  LINE *curr=in_curr;
  1337. /*--------------------------- processing ------------------------------*/
  1338. #ifdef TRACE
  1339.  trace_function("target.c:  find_next_in_scope");
  1340. #endif
  1341.  if (in_curr == NULL)
  1342.      curr = lll_find(CURRENT_FILE->first_line,line_number);
  1343.  for (;;line_number+=(LINETYPE)direction)
  1344.    {
  1345.     if (in_scope(curr))
  1346.        break;
  1347.     if (direction == DIRECTION_FORWARD)
  1348.        curr = curr->next;
  1349.     else
  1350.        curr = curr->prev;
  1351.     if (curr == NULL)
  1352.        break;
  1353.    }
  1354. #ifdef TRACE
  1355.  trace_return();
  1356. #endif
  1357.  return(line_number);
  1358. }
  1359. /***********************************************************************/
  1360. #ifdef PROTO
  1361. LINETYPE find_last_not_in_scope(LINE *in_curr,LINETYPE line_number,short direction)
  1362. #else
  1363. LINETYPE find_last_not_in_scope(in_curr,line_number,direction)
  1364. LINE *in_curr;
  1365. LINETYPE line_number;
  1366. short direction;
  1367. #endif
  1368. /***********************************************************************/
  1369. {
  1370. /*-------------------------- external data ----------------------------*/
  1371. /*--------------------------- local data ------------------------------*/
  1372.  LINE *curr=in_curr;
  1373.  LINETYPE offset=0L;
  1374. /*--------------------------- processing ------------------------------*/
  1375. #ifdef TRACE
  1376.  trace_function("target.c:  find_last_not_in_scope");
  1377. #endif
  1378.  if (in_curr == NULL)
  1379.      curr = lll_find(CURRENT_FILE->first_line,line_number);
  1380.  for (;;line_number+=(LINETYPE)direction)
  1381.    {
  1382.     if (in_scope(curr))
  1383.        break;
  1384.     if (direction == DIRECTION_FORWARD)
  1385.       {
  1386.        curr = curr->next;
  1387.        offset = (-1L);
  1388.       }
  1389.     else
  1390.       {
  1391.        curr = curr->prev;
  1392.        offset = 1L;
  1393.       }
  1394.     if (curr == NULL)
  1395.        break;
  1396.    }
  1397. #ifdef TRACE
  1398.  trace_return();
  1399. #endif
  1400.  return(line_number+offset);
  1401. }
  1402. /***********************************************************************/
  1403. #ifdef PROTO
  1404. short validate_target(CHARTYPE *string,TARGET *target,short target_type,LINETYPE true_line,bool display_parse_error,bool allow_error_display)
  1405. #else
  1406. short validate_target(string,target,target_type,true_line,display_parse_error,allow_error_display)
  1407. CHARTYPE *string;
  1408. TARGET *target;
  1409. short target_type;
  1410. LINETYPE true_line;
  1411. bool display_parse_error,allow_error_display;
  1412. #endif
  1413. /***********************************************************************/
  1414. {
  1415. /*-------------------------- external data ----------------------------*/
  1416. /*--------------------------- local data ------------------------------*/
  1417.  short rc=RC_OK;
  1418. /*--------------------------- processing ------------------------------*/
  1419. #ifdef TRACE
  1420.  trace_function("target.c:  validate_target");
  1421. #endif
  1422.  rc = parse_target(string,true_line,target,target_type,display_parse_error,allow_error_display);
  1423.  if (rc != RC_OK)
  1424.    {
  1425. #ifdef TRACE
  1426.     trace_return();
  1427. #endif
  1428.     return(RC_INVALID_OPERAND);
  1429.    }
  1430.  rc = find_target(target,true_line,display_parse_error,allow_error_display);
  1431.  if (rc != RC_OK)
  1432.    {
  1433. #ifdef TRACE
  1434.     trace_return();
  1435. #endif
  1436.     return(RC_TARGET_NOT_FOUND);
  1437.    }
  1438. #ifdef TRACE
  1439.  trace_return();
  1440. #endif
  1441.  return(RC_OK);
  1442. }
  1443. /***********************************************************************/
  1444. #ifdef PROTO
  1445. bool in_scope(LINE *curr)
  1446. #else
  1447. bool in_scope(curr)
  1448. LINE *curr;
  1449. #endif
  1450. /***********************************************************************/
  1451. {
  1452. /*-------------------------- external data ----------------------------*/
  1453. /*--------------------------- local data ------------------------------*/
  1454.  bool rc=RC_OK;
  1455. /*--------------------------- processing ------------------------------*/
  1456. #ifdef TRACE
  1457.  trace_function("target.c:  in_scope");
  1458. #endif
  1459.  if (curr->select < CURRENT_VIEW->display_low
  1460.  ||  curr->select > CURRENT_VIEW->display_high)
  1461.     rc = FALSE;
  1462.  else
  1463.     rc = TRUE;
  1464. #ifdef TRACE
  1465.  trace_return();
  1466. #endif
  1467.  return(rc);
  1468. }
  1469. /***********************************************************************/
  1470. #ifdef PROTO
  1471. void calculate_scroll_values(short *number_focus_rows,LINETYPE *new_focus_line,
  1472.                              LINETYPE *new_current_line,bool *limit_of_screen,
  1473.                              bool *limit_of_file,bool *leave_cursor,
  1474.                              short direction)
  1475. #else
  1476. void calculate_scroll_values(number_focus_rows,new_focus_line,new_current_line,
  1477.                              limit_of_screen,limit_of_file,leave_cursor,direction)
  1478. short *number_focus_rows;
  1479. LINETYPE *new_focus_line,*new_current_line;
  1480. bool *limit_of_screen,*limit_of_file,*leave_cursor;
  1481. short direction;
  1482. #endif
  1483. /***********************************************************************/
  1484. {
  1485. /*------------------------- external data -----------------------------*/
  1486. /*--------------------------- local data ------------------------------*/
  1487.  register short i=0;
  1488.  unsigned short x=0,y=0;
  1489. /*--------------------------- processing ------------------------------*/
  1490. #ifdef TRACE
  1491.  trace_function("target.c:  calculate_scroll_values");
  1492. #endif
  1493. /* getyx(CURRENT_WINDOW,y,x);*/
  1494.  *limit_of_screen = *limit_of_file = FALSE;
  1495.  *number_focus_rows = 0;
  1496.  *new_focus_line = (-1L);
  1497.  y = CURRENT_SCREEN.rows[WINDOW_MAIN];
  1498.  switch(direction)
  1499.    {
  1500.     case DIRECTION_FORWARD:
  1501. /*---------------------------------------------------------------------*/
  1502. /* Determine the new focus line and the number of rows to adjust the   */
  1503. /* cursor position.                                                    */
  1504. /*---------------------------------------------------------------------*/
  1505.          for (i=0;i<CURRENT_SCREEN.rows[WINDOW_MAIN];i++)
  1506.            {
  1507.             if (CURRENT_SCREEN.sl[i].line_number == CURRENT_VIEW->focus_line)
  1508.               {
  1509.                y = i;
  1510.                continue;
  1511.               }
  1512.             if (CURRENT_SCREEN.sl[i].line_number != (-1L)
  1513.             && y != CURRENT_SCREEN.rows[WINDOW_MAIN])
  1514.               {
  1515.                *number_focus_rows = i-y;
  1516.                *new_focus_line = CURRENT_SCREEN.sl[i].line_number;
  1517.                break;
  1518.               }
  1519.            }
  1520. /*---------------------------------------------------------------------*/
  1521. /* If we have NOT set a new focus line (because we are on the bottom   */
  1522. /* of the screen) the new focus line is the next line in scope (if     */
  1523. /* SHADOW is OFF). If SHADOW is ON, the new focus line is determined by*/
  1524. /* the status of the current focus line.                               */
  1525. /*---------------------------------------------------------------------*/
  1526.          if (*new_focus_line == (-1L))
  1527.            {
  1528.             if (CURRENT_VIEW->shadow)
  1529.               {
  1530.                *new_focus_line = CURRENT_SCREEN.sl[y].line_number +
  1531.                                  ((CURRENT_SCREEN.sl[y].number_lines_excluded == 0) ?
  1532.                                  1L :
  1533.                                  (LINETYPE)CURRENT_SCREEN.sl[y].number_lines_excluded);
  1534.               }
  1535.             else
  1536.               {
  1537.                if (CURRENT_SCREEN.sl[y].current->next != NULL)
  1538.                   *new_focus_line = find_next_in_scope(CURRENT_SCREEN.sl[y].current->next,
  1539.                                    CURRENT_SCREEN.sl[y].line_number+1L,direction);
  1540.               }
  1541.            }
  1542. /*---------------------------------------------------------------------*/
  1543. /* Determine the new current line and the number of rows to adjust the */
  1544. /* cursor position.                                                    */
  1545. /*---------------------------------------------------------------------*/
  1546.          *leave_cursor = TRUE;
  1547.          *new_current_line = (-1L);
  1548.          for (i=CURRENT_VIEW->current_row+1;i<CURRENT_SCREEN.rows[WINDOW_MAIN];i++)
  1549.            {
  1550.             if (CURRENT_SCREEN.sl[i].line_type == LINE_LINE
  1551.             ||  CURRENT_SCREEN.sl[i].line_type == LINE_TOF_EOF)
  1552.               {
  1553.                *new_current_line = CURRENT_SCREEN.sl[i].line_number;
  1554.                break;
  1555.               }
  1556.             if (CURRENT_SCREEN.sl[i].line_type == LINE_SHADOW)
  1557.                *leave_cursor = FALSE;
  1558.            }
  1559. /*---------------------------------------------------------------------*/
  1560. /* If we have NOT set a new current line (only way this can happen is  */
  1561. /* if all lines after the current line are RESERVED, SCALE or TABLINE) */
  1562. /* and the cursor is on the current line) the new current line is the  */
  1563. /* next line in scope.                                                 */
  1564. /*---------------------------------------------------------------------*/
  1565.          if (*new_current_line == (-1L))
  1566.            {
  1567.             if (CURRENT_SCREEN.sl[y].current->next != NULL)
  1568.                *new_current_line = find_next_in_scope(CURRENT_SCREEN.sl[y].current->next,
  1569.                                    CURRENT_SCREEN.sl[y].line_number+1L,direction);
  1570.            }
  1571. /*---------------------------------------------------------------------*/
  1572. /* Set flags for bottom_of_screen and bottom_of_file as appropriate.   */
  1573. /*---------------------------------------------------------------------*/
  1574.          if (*number_focus_rows == 0)
  1575.             *limit_of_screen = TRUE;
  1576.          if (CURRENT_SCREEN.sl[y].line_type == LINE_TOF_EOF
  1577.          &&  CURRENT_SCREEN.sl[y].current->next == NULL)
  1578.             *limit_of_file = TRUE;
  1579.          break;
  1580.     case DIRECTION_BACKWARD:
  1581. /*---------------------------------------------------------------------*/
  1582. /* Determine the new focus line and the number of rows to adjust the   */
  1583. /* cursor position.                                                    */
  1584. /*---------------------------------------------------------------------*/
  1585.          for (i=CURRENT_SCREEN.rows[WINDOW_MAIN]-1;i>-1;i--)
  1586.            {
  1587.             if (CURRENT_SCREEN.sl[i].line_number == CURRENT_VIEW->focus_line)
  1588.               {
  1589.                y = i;
  1590.                continue;
  1591.               }
  1592.             if (CURRENT_SCREEN.sl[i].line_number != (-1L)
  1593.             && y != CURRENT_SCREEN.rows[WINDOW_MAIN])
  1594.               {
  1595.                *number_focus_rows = y-i;
  1596.                *new_focus_line = CURRENT_SCREEN.sl[i].line_number;
  1597.                break;
  1598.               }
  1599.            }
  1600. /*---------------------------------------------------------------------*/
  1601. /* If we have NOT set a new focus line (because we are on the top      */
  1602. /* of the screen) the new focus line is the prev line in scope (if     */
  1603. /* SHADOW is OFF). If SHADOW is ON, the new focus line is determined by*/
  1604. /* the status of the current focus line.                               */
  1605. /*---------------------------------------------------------------------*/
  1606.          if (*new_focus_line == (-1L))
  1607.            {
  1608.             if (CURRENT_VIEW->shadow)
  1609.               {
  1610.                if (CURRENT_SCREEN.sl[y].line_type == LINE_SHADOW)
  1611.                   *new_focus_line = CURRENT_SCREEN.sl[y].line_number - 1L;
  1612.                else
  1613.                  {
  1614.                   if (CURRENT_SCREEN.sl[y].current->prev != NULL)
  1615.                     {
  1616.                      *new_focus_line = find_next_in_scope(CURRENT_SCREEN.sl[y].current->prev,
  1617.                                        CURRENT_SCREEN.sl[y].line_number-1L,direction);
  1618.                      if (*new_focus_line != CURRENT_SCREEN.sl[y].line_number-1L)
  1619.                         *new_focus_line++;
  1620.                     }
  1621.                  }
  1622.               }
  1623.             else
  1624.               {
  1625.                if (CURRENT_SCREEN.sl[y].current->prev != NULL)
  1626.                   *new_focus_line = find_next_in_scope(CURRENT_SCREEN.sl[y].current->prev,
  1627.                                    CURRENT_SCREEN.sl[y].line_number-1L,direction);
  1628.               }
  1629.            }
  1630. /*---------------------------------------------------------------------*/
  1631. /* Determine the new current line and the number of rows to adjust the */
  1632. /* cursor position.                                                    */
  1633. /*---------------------------------------------------------------------*/
  1634.          *leave_cursor = TRUE;
  1635.          *new_current_line = (-1L);
  1636.          for (i=CURRENT_VIEW->current_row-1;i>-1;i--)
  1637.            {
  1638.             if (CURRENT_SCREEN.sl[i].line_type == LINE_LINE
  1639.             ||  CURRENT_SCREEN.sl[i].line_type == LINE_TOF_EOF)
  1640.               {
  1641.                *new_current_line = CURRENT_SCREEN.sl[i].line_number;
  1642.                break;
  1643.               }
  1644.             if (CURRENT_SCREEN.sl[i].line_type == LINE_SHADOW)
  1645.                *leave_cursor = FALSE;
  1646.            }
  1647. /*---------------------------------------------------------------------*/
  1648. /* If we have NOT set a new current line (only way this can happen is  */
  1649. /* if all lines before the current line are RESERVED, SCALE or TABLINE)*/
  1650. /* and the cursor is on the current line) the new current line is the  */
  1651. /* previous line in scope.                                             */
  1652. /*---------------------------------------------------------------------*/
  1653.          if (*new_current_line == (-1L))
  1654.            {
  1655.             if (CURRENT_SCREEN.sl[y].current->prev != NULL)
  1656.                *new_current_line = find_next_in_scope(CURRENT_SCREEN.sl[y].current->prev,
  1657.                                   CURRENT_SCREEN.sl[y].line_number-1L,direction);
  1658.            }
  1659. /*---------------------------------------------------------------------*/
  1660. /* Set flags for top_of_screen and top_of_file as appropriate.         */
  1661. /*---------------------------------------------------------------------*/
  1662.          if (*number_focus_rows == 0)
  1663.             *limit_of_screen = TRUE;
  1664.          if (CURRENT_SCREEN.sl[y].line_type == LINE_TOF_EOF
  1665.          &&  CURRENT_SCREEN.sl[y].current->prev == NULL)
  1666.             *limit_of_file = TRUE;
  1667.          break;
  1668.    }
  1669. #ifdef TRACE
  1670.  trace_return();
  1671. #endif
  1672.  return;
  1673. }
  1674. /***********************************************************************/
  1675. #ifdef PROTO
  1676. short find_last_focus_line(unsigned short *newrow)
  1677. #else
  1678. short find_last_focus_line(newrow)
  1679. unsigned short *newrow;
  1680. #endif
  1681. /***********************************************************************/
  1682. {
  1683. /*------------------------- external data -----------------------------*/
  1684. /*--------------------------- local data ------------------------------*/
  1685.  register short i=0;
  1686.  short row=(-1);
  1687.  short rc=RC_OK;
  1688. /*--------------------------- processing ------------------------------*/
  1689. #ifdef TRACE
  1690.  trace_function("target.c:  find_last_focus_line");
  1691. #endif
  1692.  for (i=CURRENT_SCREEN.rows[WINDOW_MAIN]-1;i>-1;i--)
  1693.    {
  1694.     if (CURRENT_SCREEN.sl[i].line_number != (-1L))
  1695.       {
  1696.        *newrow = row = i;
  1697.        break;
  1698.       }
  1699.    }
  1700.  if (row == (-1))
  1701.     rc = RC_INVALID_OPERAND;
  1702. #ifdef TRACE
  1703.  trace_return();
  1704. #endif
  1705.  return(rc);
  1706. }
  1707. /***********************************************************************/
  1708. #ifdef PROTO
  1709. short find_first_focus_line(unsigned short *newrow)
  1710. #else
  1711. short find_first_focus_line(newrow)
  1712. unsigned short *newrow;
  1713. #endif
  1714. /***********************************************************************/
  1715. {
  1716. /*------------------------- external data -----------------------------*/
  1717. /*--------------------------- local data ------------------------------*/
  1718.  register short i=0;
  1719.  short row=(-1);
  1720.  short rc=RC_OK;
  1721. /*--------------------------- processing ------------------------------*/
  1722. #ifdef TRACE
  1723.  trace_function("target.c:  find_first_focus_line");
  1724. #endif
  1725.  for (i=0;i<CURRENT_SCREEN.rows[WINDOW_MAIN];i++)
  1726.    {
  1727.     if (CURRENT_SCREEN.sl[i].line_number != (-1L))
  1728.       {
  1729.        *newrow = row = i;
  1730.        break;
  1731.       }
  1732.    }
  1733.  if (row == (-1))
  1734.     rc = RC_INVALID_OPERAND;
  1735. #ifdef TRACE
  1736.  trace_return();
  1737. #endif
  1738.  return(rc);
  1739. }
  1740.